#pragma once

#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

/**
 * @brief C++中的常见可调用对象
 *    1) 函数指针
 *    2) 仿函数(具有operator()成员函数的类对象)
 *    3) 可以被转换为函数指针的类对象
 *    4) 类成员(函数)指针
*/

// case-1 函数指针
void func() {
    std::cout << __FUNCTION__ << std::endl;
}

// case-2 仿函数(具有operator()成员函数的类对象)
struct Foo {
    void operator()(void) {
        std::cout << __FUNCTION__  << std::endl;
    }
};


// case-3 可以被转换为函数指针的类对象
struct Bar {
    // fr_t 为函数指针名, void为返回参数, int & float为函数参数
    using fr_t = void(*)(int, float);    // typedef版: typedef void(*fr_t)(int, float);

    static void func(int a, float b) {
        std::cout << __FUNCTION__  << "(" << a << ", " << b <<")" << std::endl;
    }

    operator fr_t() {
        return func;
    }
    // 使用案例
    // Bar bar;
    // Bar::fr_t fptr = bar;  // 使用类型转换运算符获取函数指针
    // fptr(1, 2.0f);         // 调用函数
    // return 0;
};



// case-4 类成员(函数)指针
struct A {
    static void func(int a, float b) {
        std::cout << __FUNCTION__  << "(" << a << ", " << b <<")" << std::endl;
    }
};



int std_function();


class CallBack {
public:
    CallBack() = default;
    CallBack(const std::function<void(void)>&  f) : _callback(f) {}
    void notify() {
        _callback();              // 回调到上层
    }
private:
    std::function<void(void)> _callback;
};

int std_function_callback();


void output(int x) {
    std::cout << x << " ";
}

void call_when_even(int x, const std::function<void(int)>& f) {
    if (x % 2 == 0) {
        f(x);
    }
}

int std_function_condition_call();


///////////////////////////////////////////////////////////////////////
/**
 * @breif std::bind
 *  1). 将可调用对象与其参数绑定在一起作为仿函数延后执行;
 *  2). 将多参数函数绑定为偏函数, 延后调用
*/

void some_func(int a, float b) {
    std::cout << __FUNCTION__ << ": "<< a << ", " << b << std::endl;
}

int std_bind();


int std_bind_class();